package com.sojson.project.pay.service.wx.impl.online;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;

import com.ijpay.core.kit.WxPayKit;
import com.sojson.util.ExpUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.SystemParamUtil;
import com.sojson.util.json.JsonUtil;
import com.sojson.util.pay.wx.PayWxParamNofityVerifyInterface;
import com.sojson.util.pay.wx.WxUtil;
import com.sojson.util.pay.wx.bean.WxResponseV2;
import com.sojson.util.pay.wx.bean.WxResponseV3;
import com.sojson.util.pay.wx.constant.WxConstant;
import com.sojson.util.servlet.ServletUtil;
import com.sojson.util.xml.XmlUtil;

/**
 * 微信支付回调参数验证
 *
 * @author liu
 * @date 2021-03-16
 */
@Component
/** 是否注入这个Bean */
@Conditional(OnlineConditionPayWx.class)
public class PayWxParamNofityVerify implements PayWxParamNofityVerifyInterface {

    /**
     * 支付回调
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public WxResponseV3 payNofity(HttpServletRequest request) throws Exception {
        // 响应证书序列号
        String serial = request.getHeader("Wechatpay-Serial");
        // 响应时间戳
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        // 响应随机字符串
        String nonce = request.getHeader("Wechatpay-Nonce");
        // 响应主体
        String signature = request.getHeader("Wechatpay-Signature");

        if (StringUtil.isBlank(signature)) {
            ExpUtil.throwEx("应答证书序列号为空！");
        }
        if (StringUtil.isBlank(timestamp)) {
            ExpUtil.throwEx("应答时间戳为空！");
        }
        if (StringUtil.isBlank(nonce)) {
            ExpUtil.throwEx("应答随机串为空！");
        }
        if (StringUtil.isBlankObject(signature)) {
            ExpUtil.throwEx("应答报文主体为空！");
        }

        String stringByRequest = ServletUtil.getParamBody();
        HashMap<String, List<String>> map = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headName = headerNames.nextElement();
            Enumeration<String> headers = request.getHeaders(headName);
            List<String> list = new ArrayList<>();
            while (headers.hasMoreElements()) {
                list.add(headers.nextElement());
            }
            map.put(headName, list);
        }

        // 验证签名
        String verifyNotify = WxPayKit.verifyNotify(serial, stringByRequest, signature, nonce, timestamp,
            SystemParamUtil.getStr(WxConstant.APIV3KEY_CACHE_NAME),
            SystemParamUtil.getStr(WxConstant.CA_CERT_CACHE_KEY_PEM_WECHATPAY));

        return JsonUtil.jsonToObject(verifyNotify, WxResponseV3.class);
    }

    /**
     * 支付回调(V2接口)
     *
     * @param request
     * @return
     * @throws Exception
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public WxResponseV2 payNofityV2(HttpServletRequest request) throws Exception {
        // 从请求中获取参数
        TreeMap<String, String> treeMap = new TreeMap<>(XmlUtil.xmlToMap(ServletUtil.getParamBody()));

        // 参数验证
        String mchKey = SystemParamUtil.getStr(WxConstant.APIKEY_CACHE_NAME);
        if (!WxUtil.paySignIsSuccessObject((TreeMap)treeMap, mchKey)) {
            return null;
        }

        WxResponseV2 jsonToObject = JsonUtil.jsonToObject(JsonUtil.objectToJson(treeMap), WxResponseV2.class);
        return jsonToObject;
    }

    /**
     * 退款回调(V2接口)
     *
     * @param request
     * @return
     * @throws Exception
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public WxResponseV2 payNofityCancelV2(HttpServletRequest request) throws Exception {
        // 从请求中获取参数
        TreeMap<String, String> treeMap = new TreeMap<>(XmlUtil.xmlToMap(ServletUtil.getParamBody()));

        // 参数验证
        String mchKey = SystemParamUtil.getStr(WxConstant.APIKEY_CACHE_NAME);
        if (!WxUtil.paySignIsSuccessObject((TreeMap)treeMap, mchKey)) {
            return null;
        }

        WxResponseV2 jsonToObject = JsonUtil.jsonToObject(JsonUtil.objectToJson(treeMap), WxResponseV2.class);
        return jsonToObject;
    }

}